/**
 * Copyright (C) 2013 AirChina
 *
 * @className:com.airchina.wechat.frontend.processor.main.Delegate
 * @description:
 * 
 * @version:v1.0.0 
 * @author:larry
 * 
 * Modification History:
 * NO   Date         Author      Version     Description
 * -----------------------------------------------------------------
 *     2013-10-17     larry       v1.0.0        create
 *
 *
 */
package com.china.api.wechat.processor.main;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;

/**
 * @Description:
 * @author:larry
 * @version:v1.0.0
 * @Created:2013-10-17上午9:38:24
 * @Modified:
 */
public class Delegate {
	private final Logger log = LoggerFactory.getLogger(getClass());
	private static Map<String, Action> actions = new HashMap<String, Action>();
	private static String mainMenuPath = "/main/menu";
	private Gson gson = new Gson();
	
	public static void main(String[] args) {
		Delegate d = new Delegate();
		for(Map.Entry<String, Action> entry:actions.entrySet()){
			System.out.println(entry.getKey()+entry.getValue());
		}
		String msg = "<xml><ToUserName><![CDATA[gh_f752022b797e]]></ToUserName><FromUserName><![CDATA[oWnxKtzSBgimNngb_MCg2ONECHak]]></FromUserName><CreateTime>1386929645</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[CLICK]]></Event><EventKey><![CDATA[/subscribe/one]]></EventKey></xml>";
		try {
			d.process(msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Delegate() {
		Set<Class<?>> classes = PackageScanner.getClasses("com.china.api.wechat.processor", false);
		for (Class<?> clazz : classes) {
			if (!Processor.class.equals(clazz.getSuperclass())) {
				continue;
			}
			ActionPath clazzAn = clazz.getAnnotation(ActionPath.class);
			if (clazzAn != null) {
				Method[] methods = clazz.getMethods();
				Processor instance = null;
				for (Method method : methods) {
					ActionPath methodAn = method.getAnnotation(ActionPath.class);
					if (methodAn != null) {
						try {
							if (instance == null) {
								instance = (Processor) clazz.newInstance();
							}
							actions.put(clazzAn.path() + methodAn.path(), new Action(instance, method, methodAn.defaultReplyMappingId()));
						} catch (Exception e) {
							log.error("load action {}/{} error", clazzAn.path(), methodAn.path());
						}
					}
				}
			}
		}
	}

	public String process(String msg) throws Exception {
		Request request = new Request(msg);
		String myid = request.getValueByXPath("//ToUserName/text()");
		String msgType = request.getValueByXPath("//MsgType/text()");
		String fromUserId = request.getValueByXPath("//FromUserName/text()");
		Session session = SessionManager.getSession(fromUserId);
		log.trace("session----"+gson.toJson(session));
		HistoryFrame lastestFrame = null;
		String content = null;
		Response response = null;
		if (msgType.equals("event")) {
			content = request.getValueByXPath("//Event/text()");
			if (content.equals("subscribe")) {// 订阅事件，发送主菜单
				Action action = actions.get(mainMenuPath);
				response = action.execute(content, session);
			} else if (content.equals("unsubscribe")) {// 取消事件，主要是做记录，发送消息已经不能送达
				//SessionManager.removeSession(session);
				return "您已经取消订阅";
			} else if(content.equals("CLICK")) {	//自定义菜单
				String eventKey = request.getValueByXPath("//EventKey/text()");
				Action action = actions.get(eventKey);
				response = action.execute(content, session);
			}
		} else {
			if (!msgType.equals("text")) {
				session.clear();
				Action action = actions.get(mainMenuPath);
				response = action.execute(content, session);
			} else {
				content = request.getValueByXPath("//Content/text()");
			}
			if (session.getHistory().isEmpty() || "?".equals(content) || "？".equals(content)) {// 返回主菜单
				session.clear();
				Action action = actions.get(mainMenuPath);
				response = action.execute(content, session);
			} else if("!".equals(content) || "！".equals(content)){// 返回上级菜单
				if (session.getHistory().size() > 1) {
					session.getHistory().pop();
				}
				response = session.getHistory().peek().getResponse();
				response.setMyid(myid);
				return response.toXML();
			} else {
				lastestFrame = session.getHistory().peek();
				ReplyMapping rm = lastestFrame.getReplyMapping();
				if(rm == null){//不允许历史堆栈中的数据没有对应处理器，如果业务不需要应答需要清空session
					log.error("can't found replyMapping for response:{}", lastestFrame.getResponse().toXML());
					session.clear();
					Action action = actions.get(mainMenuPath);
					response = action.execute(content, session);
				}else{
					String path = lastestFrame.getReplyMapping().findActionPath(content);
					if(path == null){//输入项无法定位action，需要重新输入
						response = session.getHistory().peek().getResponse();
						response.setMyid(myid);
						return response.toXML();
					}
					Action action = actions.get(path);
					response = action.execute(content, session);
				}
			}
		}
		if(!session.getHistory().isEmpty()){
			HistoryFrame currentFrame = session.getHistory().peek();
			if(!currentFrame.equals(lastestFrame)){//处理器中可以移除当前帧（如需要用户重新输入），保留原来帧的输入输出信息
				currentFrame.setInMsg(content);
				currentFrame.setResponse(response);
			}
		}
		SessionManager.saveSession(session);
		//设置公众账号id
		response.setMyid(myid);
		return response.toXML();
	}
	/**
	 * 
	  *
	  * @Description:权限过滤方法
	  * @param session
	  * @param content
	  * @param response
	  * @param path
	  * @return Response
	  * @Created:zhaoxudong 2013年12月21日上午11:00:27
	  * @Modified:
	 */
	private Response filter(Session session, String content, Response response,
			String path) {
		log.info("filter...");
		return null;
	}

	/**
	 * 
	  * @Description: 记录日志
	  * @param request
	  * @param response void
	 * @throws IOException 
	 * @throws SAXException 
	 * @throws XPathExpressionException 
	  * @Created:lining 2013年12月16日下午3:53:03
	  * @Modified:
	 *//*
	private void tracking(Request request, Response response, String path) throws XPathExpressionException, SAXException, IOException {
		String bussType = "";
		switch (path) {
			case "/subscribe/one": bussType = "机票预定"; break;
			case "/check_in/one": bussType = "办理乘机"; break;
			case "/fliht_number/one": bussType = "航班动态"; break;
			case "/member/accountInfo": bussType = "个人信息"; break;
			case "/member/distanceQuery": bussType = "里程查询"; break;
			case "/member/distanceAdd": bussType = "里程补登"; break;
			case "/member/myCard": bussType = "我的知音卡"; break;
			case "/opinion/one": bussType = "意见反馈"; break;
			case "/ordermanager/getNopay": bussType = "订单管理"; break;
			case "/more/promtion": bussType = "促销公告"; break;
			default: break;
		}
		
		String openId = request.getValueByXPath("//FromUserName//text()");
		//请求
		String msgType = request.getValueByXPath("//MsgType/text()");
		
		if("text".equals(msgType)) {
			log.info(request.getValueByXPath("//Content/text()"));
		} else if("event".equals(msgType)) {
			log.info(request.getValueByXPath("//EventKey/text()"));
		}
		//回复
		if(response instanceof TextResponse) {
			TextResponse textResponse = (TextResponse) response;
			//文字消息
			log.info("TextResponse...");
		}else if(response instanceof ImageResponse) {
			ImageResponse imageResponse = (ImageResponse) response;
			//图片消息
			log.info("ImageResponse...");
		} else if(response instanceof PictureResponse) {
			PictureResponse pictureResponse = (PictureResponse) response;
			//图文消息
			log.info("PictureResponse...");
		} 
	
	}
	*/
	
}
